
(* demo of teacher ========================================================== *)
let rec append l1 l2 = 
	match l1 with
		| [] -> l2
		| head::tail -> head::(append tail l2)
append [1;2;3] [4;5;6]

(* q1 : reduce dimension of list-of-list ==================================== *)
let rec redim md_list = 
	match md_list with
		| [] -> []
		| head::tail -> append head (redim tail)
redim [[1;2;9];[];[5;6]]

(* q2 : count positive number in list ======================================= *)
let rec count li = 
	match li with
		| [] -> 0
		| head::tail -> if head > 0 then ( 1 + (count tail) ) 
										else (count tail)
count []
count [5]
count [2;4;-6;0]
count [-1;0;3;-4;0;6;-2;8;9]

(* q3 : remove matched members in a list ==================================== *)
let rec remove list target = 
	match list with
		| [] -> []
		| head::tail -> if head = target then (remove tail target) 
										else head::(remove tail target)
remove [1;2;3;4;3;5;3;3;3;9] 3

(* q4 : check if matched members exists ===================================== *)
let rec member list mem = 
	match list with
		| [] -> false
		| head::tail -> if head = mem then true else (member tail mem)
member [3;2;2;3] 1
member [3;2;1;2;3] 1

(* q5 : raise exception if duplication occurs =============================== *)
exception Duplicate
let rec check_duplicate list = 
	match list with
		| [] -> ()
		| head::tail -> if (member tail head) then (raise Duplicate)
										else (check_duplicate tail)
check_duplicate [1;2;3;8;4]

(* q6 : check existance of members ========================================== *)
exception No_existance
let rec exists list1 list2 =
	match list2 with
		| [] -> if list1 = [] then (raise No_existance) else ()
		| head::tail -> if (member list1 head) then (exists list1 tail)
										else (raise No_existance)
exists [1;2;3;6] [1;3;2;2;6;3;3;1;2;3;2]

(* q7 : result of following phrase ========================================== *)
type number = Int of int | Float of float
let a = [Int 1; Float 2.0]
let a = [Int 1; Float 2.0; Float 3.1; Int 4; Float 5.2]

(* q8 : int-to-float convertion in OCaml functions ========================== *)
let a = 9
float_of_int(a)
float a

(* q9 : multiplication in custom-type "number" ============================== *)
let mul2 n1 n2 = 
	match n1 with
		| Int i -> (
									match n2 with
										| Int b -> Int (i * b)
										| Float c -> Float ((float i) *. c)
							 ) 
							(* if there 's no "()" here, *)
							(* the following "match" is considered of the nearest match *) 
		| Float f -> match n2 with
			| Int b -> Float (f *. (float b))
			| Float b -> Float (f *. b)
mul2 (Float 7.0) (Int 8)
mul2 (Int 8) (Float 7.0)
mul2  (Int 8) (Int 8)

(* q10 : multiplication of all members in a list ============================ *)
exception Empty_list
let rec mul list = 
	match list with
		| [] -> raise Empty_list
		| head::tail -> match tail with 
			(* here : func becomes longer cuz of checking for empty list *)
			| [] -> head
			| h::t -> mul2 head (mul tail)
mul []
mul [Int 1; Int 2]
mul [Int 1; Float 2.0; Float 3.0]

(* q11 : write the expression 7 + 2.0 * 3.0 - 1 using expr type =============== *)
type expr = BinExpr of binop * expr * expr | Int of int | Float of float
	and binop = Plus | Minus | Mult | Div
let e = BinExpr(Mult, BinExpr(Plus, (Int 1),(Float 2.0)), (Float 3.0))
let o = BinExpr(Minus, BinExpr(Plus, (Int 7), BinExpr(Mult, (Float 2.0), (Float 3.0))), (Int 1))